﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Firefly.Net;
using Firefly.Data;
using Firefly.Controls;

namespace Firefly {
    public class World : TabPage {

        public GameConnection Connection { get; private set; }
        public WorldConfig Config { get; private set; }
        public bool NewActivity { get { return (mActivityLevel > 0) ? true : false; } }

        public event EventHandler OnLoad;
        public event EventHandler OnConnect;
        public event EventHandler OnDisconnect;
        public event EventHandler OnActivity;

        /// <summary>
        /// Used for quick connects.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="server"></param>
        /// <param name="port"></param>
        public World(string name, string server, int port) {
            this.Config = new WorldConfig();
            this.Config.WorldName = name;
            this.Config.ServerAddress = server;
            this.Config.ServerPort = port;

            InitializeComponents();
        }

        /// <summary>
        /// Used for loading existing worlds.
        /// </summary>
        /// <param name="name"></param>
        public World(string name) {
            this.Config = Data.WorldFile.Load(name);
            InitializeComponents();
        }

        public void InitiateConnection() {
            // Set up the connection
            Connection = new GameConnection(Config.ServerAddress, Config.ServerPort);
            Connection.ConnectionStatusChangeEvent += new GameConnection.ConnectionStatusEventHandler(delegate(GameConnection c, ConnectionStatusEventArgs e) {
                terminalOutput.AppendText(e.Output);
                // Fire ze events! AKA, connection handling.
                this.textBoxInput.InputOK = e.Connected;
                if (OnConnect != null && e.Connected) {
                    OnConnect.Invoke(this, null);
                }
                if (OnDisconnect != null && e.Connected) {
                    OnDisconnect.Invoke(this, null);
                }
                if (OnActivity != null)
                    OnActivity.Invoke(this, null);
            });
            Connection.DataReceivedEvent += new GameConnection.DataReceivedHandler(delegate(GameConnection c, string s) {
                terminalOutput.AppendText(s);
                if (OnActivity != null)
                    OnActivity.Invoke(this, null);
            });
            // Hook onto application quit event for a clean disconnection.
            Program.OnApplicationQuit += new EventHandler(delegate(object s, EventArgs e) {
                Connection.Disconnect();
            });
            // Initiate connection
            Connection.Connect();
        }

        private void InitializeComponents() {
            this.splitContainer1 = new System.Windows.Forms.SplitContainer();
            this.textBoxInput = new Controls.InputTextBox();
            this.terminalOutput = new Firefly.Controls.Terminal();
            //((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
            this.splitContainer1.Panel1.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            this.SuspendLayout();
            // 
            // tabPage1
            // 
            this.BorderStyle = BorderStyle.None;
            this.Controls.Add(this.splitContainer1);
            this.Location = new System.Drawing.Point(4, 22);
            this.Name = Config.WorldName;
            this.Padding = new System.Windows.Forms.Padding(0);
            this.Size = new System.Drawing.Size(940, 578);
            this.TabIndex = 0;
            this.Text = Config.WorldName;
            this.UseVisualStyleBackColor = true;
            // 
            // splitContainer1
            // 
            this.splitContainer1.BorderStyle = BorderStyle.FixedSingle;
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
            this.splitContainer1.Location = new System.Drawing.Point(3, 3);
            this.splitContainer1.Name = "splitContainer1";
            this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
            // 
            // splitContainer1.Panel1
            // 
            this.splitContainer1.Panel1.BorderStyle = BorderStyle.None;
            this.splitContainer1.Panel1.Controls.Add(this.terminalOutput);
            this.splitContainer1.Size = new System.Drawing.Size(934, 572);
            this.splitContainer1.SplitterDistance = 448;
            this.splitContainer1.TabIndex = 0;
            //
            // splitContainer1.Panel2
            //
            this.splitContainer1.Panel2.Controls.Add(textBoxInput);
            // 
            // terminalOutput
            // 
            this.terminalOutput.BackColor = Config.OutputWindowColor;
            this.terminalOutput.BorderStyle = BorderStyle.None;
            this.terminalOutput.Dock = System.Windows.Forms.DockStyle.Fill;
            this.terminalOutput.Font = Config.OutputFont;
            this.terminalOutput.Location = new System.Drawing.Point(0, 0);
            this.terminalOutput.Name = "terminalOutput";
            this.terminalOutput.Size = new System.Drawing.Size(934, 448);
            this.terminalOutput.TabIndex = 0;
            this.terminalOutput.Text = "";
            //
            // textBoxInput
            //
            this.textBoxInput.Dock = DockStyle.Fill;
            this.textBoxInput.Font = Config.InputFont;
            this.textBoxInput.ForeColor = Config.InputFontColor;
            this.textBoxInput.BackColor = Config.InputWindowColor;
            this.textBoxInput.BackColor = System.Drawing.Color.Black;
            this.textBoxInput.SendInput += new Firefly.Controls.InputTextBox.SendInputHandler(textBoxInput_SendInput);
            // Rest
            this.ResumeLayout(false);
            this.splitContainer1.Panel1.ResumeLayout(false);
            //((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
            this.splitContainer1.ResumeLayout(false);

            // Loading done.
            if(OnLoad != null)
                OnLoad.Invoke(this, null);
        }

        /*void textBox_KeyDown(object sender, KeyEventArgs e) {
            RichTextBox textBox = (RichTextBox)sender;

            if (e.KeyCode != mLastKeyDown && Keys.Control != e.Modifiers) {
                if (e.KeyCode == Keys.C) {
                    // Copy shortcut    
                    Clipboard.SetText(textBox.SelectedText);
                }
                else if (e.KeyCode == Keys.V) {
                    // Paste shortcut
                    if (!textBox.ReadOnly) {
                        if (textBox.SelectionLength > 0)
                            textBox.SelectedText = String.Empty;
                        textBox.SelectedText = Clipboard.GetText();
                    }
                }
                else if (e.KeyCode == Keys.X) {
                    // Cut shortcut
                    Clipboard.SetText(textBox.SelectedText);
                    if (!textBox.ReadOnly)
                        textBox.SelectedText = String.Empty;
                }
                else if (e.KeyCode == Keys.F) {
                    // Find shortcut
                }
            }
            // To avoid repeats
            mLastKeyDown = e.KeyCode;
        }*/

        private void textBoxInput_SendInput(object sender, string s) {
            // Write to buffer.
            Connection.Write(s + "\n");
        }

        protected override void OnGotFocus(EventArgs e) {
            if (NewActivity)
                this.mActivityLevel = 0;
            base.OnGotFocus(e);
        }

        

        private int mActivityLevel = 0;
        private Keys mLastKeyDown;
        private System.Windows.Forms.SplitContainer splitContainer1;
        private Controls.Terminal terminalOutput;
        private Controls.InputTextBox textBoxInput;
    }
}
